package com.itstyle.quartz.config;

import com.itstyle.quartz.service.impl.AuthService;
import com.mysql.cj.protocol.AuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

/**
 * @author 张霄峰
 * @email 29839415@qq.com
 * @date 2020/4/14 13:26
 */
@Configuration
@EnableWebSecurity
@Order(2)
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法安全设置
//@ComponentScan("com.itstyle.quartz.service.impl")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //***************************数据库验证--------------
    @Autowired
    private AuthService userDetailsService;
    //private AuthService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();   // 使用 BCrypt 加密，密码以明文的方式进行匹配不然会报错
    }

    /**
     * 取出验证信息
     *
     * @return
     */
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        System.out.println("验证信息----------------");
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder); // 设置密码加密方式
        return authenticationProvider;
    }

//***************************数据库验证----------

    /**
     * 自定义配置,定义http安全规则
     * <p>
     * 数据库角色需要写 ROLE_ADMIN 对应权限认证的 ADMIN
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        System.out.println("认证请求验证----------------");
        //认证请求
        http.authorizeRequests()
                .antMatchers("/static/**","/AdminLTE/**","/bootstrap/**","/cron/**","/flat_ui/**","/font-awesome/**","/Ionicons/**","/iview/**","/layer/**","/libs/**","/common.js", "/swagger-ui.html", "/webjars/**", "/v2/**", "/swagger-resources/**", "/main.shtml").permitAll() // 都可以访问
                .antMatchers("/main.shtml").hasRole("ADMIN") // 需要相应的角色才能访问(区分大小写)
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/").permitAll()//这里程序默认路径就是登陆页面，允许所有人进行登陆
                .loginProcessingUrl("/log")//登陆提交的处理url
                .failureForwardUrl("/?error=true")//登陆失败进行转发，这里回到登陆页面，参数error可以告知登陆状态
                .defaultSuccessUrl("/")//登陆成功的url，这里去到个人首页
                .and()
                .logout()
                .logoutUrl("/logout").permitAll()
                .logoutSuccessUrl("/?logout=true")//按顺序，第一个是登出的url，security会拦截这个url进行处理，所以登出不需要我们实现，第二个是登出url，logout告知登陆状态
                .and()
                .rememberMe()
                .tokenValiditySeconds(604800)//记住我功能，cookies有限期是一周
                .rememberMeParameter("remember-me")//登陆时是否激活记住我功能的参数名字，在登陆页面有展示
                .rememberMeCookieName("workspace")//cookies的名字，登陆后可以通过浏览器查看cookies名字
                .and()
                .csrf().disable();
// 指定登陆信息所使用的数据源

// .tokenRepository(tokenRepository);


    }
    /**
     * 认证信息管理
     *
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        /**
         * todo 通过数据库进行查询验证----------------
         *  我们需要在 service 层中实现 userDetailsService
         */
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }

    public static void main(String[] args) {
        String a = new BCryptPasswordEncoder().encode("123456");
        System.out.println(a);
    }
}
